﻿namespace ScrumLite.WebUx.Tests
{
    using System.Configuration;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using ScrumLite.Services;
    using ScrumLite.WebUx.Controllers;
    using ScrumLite.WebUx.Models;
    using System;
    using ScrumLite.Services.Contracts;
    using System.Globalization;
using System.Security.Permissions;
    using System.Web.Mvc;

    /// <summary>
    /// Summary description for RequestsControllerFixture
    /// </summary>
    [TestClass]
    public class DefectsControllerFixture
    {
        MockDeliverablesService deliverablesService;

        [TestInitialize]
        public void Initialize()
        {
            this.deliverablesService = new MockDeliverablesService();
        }

        [TestMethod]
        public void ShouldShowAllDefects()
        {
            MockDefectsService service = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(service, new MockProfileService(), this.deliverablesService);

            controller.Read(Guid.NewGuid().ToString(), "All");

            Assert.IsNotNull(controller.DataToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(DefectsReadViewData));
        }

        [TestMethod]
        public void ShouldShowDefect()
        {
            MockDefectsService service = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(service, new MockProfileService(), this.deliverablesService);

            controller.ReadOne(Guid.NewGuid().ToString(), 4);

            Assert.IsNotNull(controller.DataToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(DefectsWriteViewData));
            Assert.AreEqual("Defect 4", ((DefectsWriteViewData)controller.DataToShow).Defect.Title);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldDefectBeNullOnNew()
        {
            MockDefectsService service = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(service, new MockProfileService(), this.deliverablesService);

            controller.New(Guid.NewGuid().ToString(),1);

            Assert.IsInstanceOfType(controller.DataToShow, typeof(DefectsWriteViewData));
            Assert.IsNull(((DefectsWriteViewData)controller.DataToShow).Defect);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldReturnAllDefectsInNew()
        {
            int index = 4;
            string project = this.deliverablesService.ProjectToReturn[index];
            MockDefectsService service = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(service, new MockProfileService(), this.deliverablesService);

            controller.New(project,1);

            Assert.AreEqual(((DefectsWriteViewData)controller.DataToShow).Deliverables.Count,this.deliverablesService.DeliverablesToReturn[project].Count);

            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][0].FullName));
            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][1].FullName));
            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][2].FullName));
            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][3].FullName));
            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][4].FullName));
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldReturnAllDefectsInReadOne()
        {
            int index = 4;
            int defectMoniker = 1;
            string project = this.deliverablesService.ProjectToReturn[index];
            MockDefectsService service = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(service, new MockProfileService(), this.deliverablesService);

            controller.ReadOne(project, defectMoniker);

            Assert.AreEqual(((DefectsWriteViewData)controller.DataToShow).Deliverables.Count, this.deliverablesService.DeliverablesToReturn[project].Count);

            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][0].FullName));
            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][1].FullName));
            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][2].FullName));
            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][3].FullName));
            Assert.IsTrue(((DefectsWriteViewData)controller.DataToShow).Deliverables.ContainsValue(this.deliverablesService.DeliverablesToReturn[project][4].FullName));
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldReadAllDefectsByDeliverable()
        {
            MockDefectsService service = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(service, new MockProfileService(), this.deliverablesService);

            controller.ReadByDeliverable(Guid.NewGuid().ToString(), Guid.NewGuid().ToString());

            Assert.IsNotNull(controller.DataToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(DefectsReadViewData));
        }

        [TestMethod]
        public void ShouldSelectDefectDeliverable()
        {
            int index = 4;
            int defectMoniker = 1;
            string project = this.deliverablesService.ProjectToReturn[index];
            MockDefectsService service = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(service, new MockProfileService(), this.deliverablesService);

            controller.ReadOne(project, defectMoniker);

            Assert.AreEqual(((DefectsWriteViewData)controller.DataToShow).DeliverableMoniker, defectMoniker);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldAddDefect()
        {
            int index = 4;
            int deliverableMoniker = 1;
            string project = this.deliverablesService.ProjectToReturn[index];
            MockDeliverablesService deliverableService = new MockDeliverablesService();
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, new MockProfileService(), this.deliverablesService);
            Guid deliverableId = new Guid(deliverableService.GetDeliverableByMoniker(project, deliverableMoniker).ToString());

            Defect defect = new Defect() { Id = Guid.NewGuid(), Moniker = 0, Notes = null, Title = "Defect 8", Decision = null, CreatedOn = DateTime.Now.AddDays(-20), CreatedBy = "User2", Severity = 1, TriagedOn = null, DeliverableId = deliverableId, Triaged = false, DaysOpen = 0 };

            controller.Write(project, 0, null, deliverableMoniker, defect.Title, defect.Notes, defect.Decision, defect.CreatedOn, defect.CreatedBy, defect.Severity);

            Assert.IsTrue(defectsService.AddDefectsCalled);

            Assert.AreEqual(defectsService.DefectAdded.Decision, defect.Decision);
            Assert.AreEqual(defectsService.DefectAdded.CreatedBy, defect.CreatedBy);
            Assert.AreEqual(defectsService.DefectAdded.CreatedOn, defect.CreatedOn);
            Assert.AreEqual(defectsService.DefectAdded.DaysOpen, defect.DaysOpen);
            Assert.AreEqual(defectsService.DefectAdded.DeliverableId, deliverableId);
            Assert.AreEqual(defectsService.DefectAdded.Moniker, (defectsService.GetNextMoniker(project) - 1));
            Assert.AreEqual(defectsService.DefectAdded.Notes, defect.Notes);
            Assert.AreEqual(defectsService.DefectAdded.Severity, defect.Severity);
            Assert.AreEqual(defectsService.DefectAdded.Title, defect.Title);
            Assert.AreEqual(defectsService.DefectAdded.Triaged, defect.Triaged);
            Assert.AreEqual(defectsService.DefectAdded.TriagedOn, defect.TriagedOn);
        }

        [TestMethod]
        public void ShouldRenderDefectsWithData()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockDefectsService service = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(service, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            Assert.AreEqual("DefectsMetrics", controller.ViewToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(DefectsMetricsData));
            Assert.IsInstanceOfType(controller.DataToShow, typeof(ContextViewData));
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        [Ignore]
        public void ShouldCallGetDefectsOnRenderDefectsView()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockDefectsService defectsService = new MockDefectsService();
            defectsService.GetDefectsCalled = false;
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            Assert.IsTrue(defectsService.GetDefectsCalled);
            Assert.AreEqual(mockProjectUri, defectsService.ProjectId);
            Assert.AreEqual(3, ((DefectsMetricsData)controller.DataToShow).DefectsTriaged);
            Assert.AreEqual(2, ((DefectsMetricsData)controller.DataToShow).DefectsNotTriaged);
            Assert.AreEqual(2, ((DefectsMetricsData)controller.DataToShow).ToTriage0To1);
            Assert.AreEqual(1, ((DefectsMetricsData)controller.DataToShow).ToTriage1To5);
            Assert.AreEqual(1, ((DefectsMetricsData)controller.DataToShow).ToTriage5To20);
            Assert.AreEqual(1, ((DefectsMetricsData)controller.DataToShow).ToTriageMoreThan20);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsWriteViewData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldGenerateTimeToTriagePieUrl()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            string expectedUrl = @"http://chart.apis.google.com/chart?cht=p3&chs=450x150&chd=t:2.0,1.0,1.0,1.0&chtt=Time+to+triage&chl=0%20to%201%20day%20(2)|1%20to%205%20days%20(1)|5%20to%2020%20days%20(1)|more%20than%2020%20days%20(1)";
            Assert.AreEqual(expectedUrl, ((DefectsMetricsData)controller.DataToShow).GChartTimeToTriagePie);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldGenerateEmptyTimeToTriagePieUrl()
        {
            string mockProjectUri = MockDefectsService.ProjectIdForEmptyData;
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            string expectedUrl = String.Format(CultureInfo.InvariantCulture,"/{0}/{1}", ConfigurationManager.AppSettings["SiteImagesPath"], "chart_EmptyTimeToTriagePie.png");
            Assert.AreEqual(expectedUrl, ((DefectsMetricsData)controller.DataToShow).GChartTimeToTriagePie);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldGenerateTimeToTriageBarsUrl()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            string expectedUrl = @"http://chart.apis.google.com/chart?cht=bvg&chs=400x150&chd=t:20.0,10.0,10.0,10.0&chtt=Time+to+triage&chxt=x,y&chxl=0:|0-1|1-5|5-20|%3E20|1:&chxr=1,0,10&chbh=20,5,50";
            Assert.AreEqual(expectedUrl, ((DefectsMetricsData)controller.DataToShow).GChartTimeToTriageBars);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldGenerateEmptyTimeToTriageBarsUrl()
        {
            string mockProjectUri = MockDefectsService.ProjectIdForEmptyData;
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            string expectedUrl = String.Format(CultureInfo.InvariantCulture,"/{0}/{1}", ConfigurationManager.AppSettings["SiteImagesPath"], "chart_EmptyTimeToTriageBars.png");
            Assert.AreEqual(expectedUrl, ((DefectsMetricsData)controller.DataToShow).GChartTimeToTriageBars);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldGenerateEmptyDefectsPieUrl()
        {
            string mockProjectUri = MockDefectsService.ProjectIdForEmptyData;
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            string expectedUrl = String.Format(CultureInfo.InvariantCulture,"/{0}/{1}", ConfigurationManager.AppSettings["SiteImagesPath"], "chart_EmptyDefectsPie.png");
            Assert.AreEqual(expectedUrl, ((DefectsMetricsData)controller.DataToShow).GChartDefectsPie);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldGenerateDefectsPieUrl()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            string expectedUrl = @"http://chart.apis.google.com/chart?cht=p3&chs=450x150&chd=t:3.0,2.0&chtt=Defects&chl=Defects%20triaged%20(3)|Defects%20not%20triaged%20(2)";
            Assert.AreEqual(expectedUrl, ((DefectsMetricsData)controller.DataToShow).GChartDefectsPie);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldGenerateDefectsBarsUrl()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            string expectedUrl = @"http://chart.apis.google.com/chart?cht=bvg&chs=400x150&chd=t:30.0,20.0&chtt=Defects&chxt=x,y&chxl=0:|Triaged|Not%20triaged|1:&chxr=1,0,10&chbh=20,5,50";
            Assert.AreEqual(expectedUrl, ((DefectsMetricsData)controller.DataToShow).GChartDefectsBars);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }

        [TestMethod]
        public void ShouldGenerateEmptyDefectsBarsUrl()
        {
            string mockProjectUri = MockDefectsService.ProjectIdForEmptyData;
            MockDefectsService defectsService = new MockDefectsService();
            TestableDefectsController controller = new TestableDefectsController(defectsService, this.deliverablesService);

            controller.DefectsMetrics(mockProjectUri);

            string expectedUrl = String.Format(CultureInfo.InvariantCulture,"/{0}/{1}", ConfigurationManager.AppSettings["SiteImagesPath"], "chart_EmptyDefectsBars.png");
            Assert.AreEqual(expectedUrl, ((DefectsMetricsData)controller.DataToShow).GChartDefectsBars);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectId);
            Assert.IsNotNull(((DefectsMetricsData)controller.DataToShow).ProjectName);
        }
    }

    public class TestableDefectsController : DefectsController
    {
        public object DataToShow { get; set; }
        public object ViewToShow { get; set; }
        public object DataRedirectToAction { get; set; }

        public TestableDefectsController(IDefectsService service, IDeliverablesService deliverableService)
            : base(service, new MockProjectsService(), deliverableService, new MockProfileService() )
        {
        }

        public TestableDefectsController(IDefectsService service, IProfileService profile, IDeliverablesService deliverableService)
            : base(service, new MockProjectsService(), deliverableService, profile)
        {            
        }

        [SecurityPermission(SecurityAction.LinkDemand,Unrestricted=true)]
        protected override void RenderView(string viewName, string masterName, object viewData)
        {
            ViewToShow = viewName;
            DataToShow = viewData;
        }
        protected override void RedirectToAction(object values)
        {
            DataRedirectToAction = values;
        }
    }
}
